import * as Highlighter from '../highlighter.js'
import MarkdownParser from "../markdown-parser.js"
import TextareaWithHighlight from '../textarea-with-highlight.js'
import D from "../delegator.js"
import {TypeCheck} from "../common.js"
import * as UI from "../ui.js"

class BasePane {
    constructor(widgetContent, ui) {
        this._widgetContent = widgetContent;
        this._Init();
        this._ui = ui;
    }
    Destroy(){
        this._ui.Release();
        this._ui = undefined;
    }
    get element() {return this._ui.element;}
    get ui() {return this._ui;}
    _Init() {}
    SetWidgetContentData(value) {this._widgetContent.data = value;}
    GetWidgetContentData() {return this._widgetContent.data;}
    //SetWidgetName(name) {
        //D(this.element).AddAttribute('data-language', name);
    //}
    /// virtual functions;
    Render() {}
    Upload() {}
    /// end of virtual functions;
    GetMenuElements(){
        return [];
    }
    SetFocus() {}
    SetBlur() {}
}

export class EditPane extends BasePane {
    constructor(wc, ui, highlightLanguage) {
        super(wc, ui ?? UI.UIPaneEdit());
        this._editor = new TextareaWithHighlight(
            this._ui.element,
            highlightLanguage,
            this._GetText()
        );
    }
    Destroy() {
        this._editor.Destroy();
        super.Destroy();
    }
    _Init() {
        if(!this.GetWidgetContentData()) {
            this.SetWidgetContentData('');
        }
    }
    _GetText() {return this.GetWidgetContentData();}
    SetUpdateCallback(fn) {
        this._editor.SetUpdateCallback(fn);
    }
    SetFocus(){
        this._ui.Focus();
    }
    SetBlur(){
        this._ui.Blur();
    }
    Upload() {
        this.SetWidgetContentData(this._editor.GetText());
    }
}

export class TextEditPane extends EditPane {
    constructor(wc) {
        super(wc, null, 'plaintext');
        //this.SetWidgetName('text');
    }
}
export class HTMLEditPane extends EditPane {
    constructor(wc) {
        super(wc, null, 'xml');
        //this.SetWidgetName('HTML');
    }
}

export class MarkdownEditPane extends EditPane {
    constructor(wc) {
        super(wc, null, 'markdown');
        //this.SetWidgetName('Markdown');
    }
}

const _TEMPLATE_ = Object.freeze({
    content: "std::cout<<\"Hello World\";",
    language: "cpp",
});
export class CodeEditPane extends EditPane {
    constructor(wc) {
        super(wc);
        //this.SetWidgetName('code');
        this._editor.SetLanguage(this._data.language);
        this._arrMenuOption = [];
    }

    _Init() {
        let _data = this.GetWidgetContentData();
        if(!TypeCheck.IsObject(_data)) {
            _data = JSON.parse(JSON.stringify(_TEMPLATE_));
            this.SetWidgetContentData(_data);
        }
        this._data = _data;
    }

    _GetText() {return this._data.content;}

    /*
    _MenuClicked(e) {
        if(D(e.target).HasAttribute('data-slog-link')) {
            const _lang = D.GetDatasetValue('slogLink');
            //this._arrMenuOption[0].innerText = _lang;
            this._data.language = _lang;
            this._editor.SetLanguage(_lang);
        }
    }
    */
    Upload() {
        this._data.content = this._editor.GetText();
    }

    //GetMenuElements(){
        //return this._arrMenuOption;
    //}
}


//================================================================================
// view panes
export class TextViewPane extends BasePane {
    constructor(wc) {
        super(wc, UI.UIPaneView());
    }
    Render() {
        this._ui.SetText(this.GetWidgetContentData());
        return this;
    }
}
export class HTMLViewPane extends BasePane {
    constructor(wc) {
        super(wc, UI.UIPaneView());
    }
    Render() {
        this._ui.SetHTML(this.GetWidgetContentData());
        return this;
    }
}
export class MarkdownViewPane extends BasePane {
    constructor(wc) {
        super(wc, UI.UIPaneView());
    }
    Render() {
        this._ui.SetHTML(MarkdownParser.MarkdownStringToHTML(this.GetWidgetContentData()));
        return this;
    }
}

export class CodeViewPane extends BasePane {
    constructor(wc) {
        super(wc, UI.UIPaneViewCode());
    }
    Render() {
        try {
            const _lang = this.GetWidgetContentData().language;
            const _text = this.GetWidgetContentData().content;
            this._ui.SetLanguage(_lang);
            this._ui.SetText(_text);
            Highlighter.LoadLanguage(_lang)
                .then(() => {
                    this._ui.SetHTML(Highlighter.Highlight(_text, _lang));
                });
        } catch(e) {
            this._ui.SetCode(e.message);
        }
        return this;
    }
}
